const defaultOpts = {};

const ps = {
  init(env) {
    env.names = {};
  },
  Program(node, env) {
    let item;
    for (item of node.body) {
      ps.process(item, env);
    }
  },
  VariableDeclaration(node, env) {
    node.declarations.forEach((item) => {
      ps.process(item, env);
    });
  },
  VariableDeclarator(node, env) {
    env.names[ps.process(node.id, env, { name: true })] = node.init ? ps.process(node.init, env) : undefined;
  },
  Identifier(node, env, opts) {
    if (!opts.name) return env.names[node.name];
    return node.name;
  },
  Literal(node, env) {
    return eval(node.raw);
  },
  WhileStatement(node, env) {
    while (ps.process(node.test, env)) {
      ps.process(node.body, env)
    }
  },
  IfStatement(node, env) {
    if (ps.process(node.test, env)) {
      ps.process(node.consequent, env)
    } else {
      ps.process(node.alternate, env)
    }
  },
  BinaryExpression(node, env) {
    switch (node.operator) {
      case '<=': {
        return ps.process(node.left, env) <= ps.process(node.right, env)
      }
      case '<': {
        return ps.process(node.left, env) < ps.process(node.right, env)
      }
      case '+': {
        return ps.process(node.left, env) + ps.process(node.right, env);
      }
    }
  },
  BlockStatement(node, env) {
    let item;
    for (item of node.body) {
      ps.process(item, env);
    }
  },
  ExpressionStatement(node, env) {
    return ps.process(node.expression, env);
  },
  AssignmentExpression(node, env) {
    switch (node.operator) {
      case '=': {
        env.names[ps.process(node.left, env, { name: true })] = ps.process(node.right, env);
        break;
      }
    }
  },
  process(node, env, opts) {
    const p = ps[node.type];
    if (!p) {
      console.error('未处理的类型', node.type, node);
      return;
    }
    const result = p(node, env, opts || defaultOpts);
    return result;
  },
};

export default ps;
